#!/bin/sh

. "$SPEC_PATH/abstract/patroni"

e2e_test_extra_hash() {
  "$SHELL" "$PROJECT_PATH/stackgres-k8s/ci/build/build-functions.sh" path_hash \
    "$(realpath --relative-to "$PROJECT_PATH" "$SPEC_PATH/abstract/patroni")"
}

e2e_test_install() {
  kubectl create namespace "$CLUSTER_NAMESPACE"
  wait_until eval 'kubectl get secret -n "$OPERATOR_NAMESPACE" stackgres-operator-certs -o json | \
    jq ".data|has(\"tls.crt\") and has(\"tls.key\")" | grep -xqF true'
  kubectl get secret -n "$OPERATOR_NAMESPACE" stackgres-operator-certs -o json \
    | jq ".metadata = { namespace: \"$CLUSTER_NAMESPACE\", name: \"ssl-provided\" }" \
    | kubectl create -f -
  create_or_replace_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE" "2" \
    --set cluster.postgres.ssl.enabled=false

  wait_pods_running "$CLUSTER_NAMESPACE" 2
  wait_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE"
  switch_cluster_to_first "$CLUSTER_NAME" "$CLUSTER_NAMESPACE"
}

e2e_test() {
  run_test "Checking that is possible to connect using only SSL with generated certificate" generated_ssl_check

  run_test "Checking that is possible to connect using only SSL with provided certificate" provided_ssl_check

  run_test "Checking that is possible to connect not using SSL" no_ssl_check

  run_test "Checking that replication is connected using SSL" replication_ssl_check
}

generated_ssl_check() {
  create_or_replace_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE" "2" \
    --set cluster.postgres.ssl.enabled=true \
    --set cluster.postgres.ssl.certificateSecretKeySelector=null \
    --set cluster.postgres.ssl.privateKeySecretKeySelector=null

  wait_until kubectl exec -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-0" -c patroni -- ls /etc/ssl/tls.key

  ssl_check
}

provided_ssl_check() {
  create_or_replace_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE" "2" \
    --set cluster.postgres.ssl.enabled=true \
    --set-string cluster.postgres.ssl.certificateSecretKeySelector.name=ssl-provided \
    --set-string cluster.postgres.ssl.certificateSecretKeySelector.key=tls.crt \
    --set-string cluster.postgres.ssl.privateKeySecretKeySelector.name=ssl-provided \
    --set-string cluster.postgres.ssl.privateKeySecretKeySelector.key=tls.key

  wait_until eval '[ "$(kubectl get secret -n "$CLUSTER_NAME" ssl-provided --template "{{ .data \"tls.crt\" }}")" = \
    "$(kubectl get secret -n "$CLUSTER_NAME" ssl-ssl --template "{{ .data \"tls.crt\" }}")" ]'
  wait_until eval '[ "$(kubectl get secret -n "$CLUSTER_NAME" ssl-provided --template "{{ .data \"tls.key\" }}")" = \
    "$(kubectl get secret -n "$CLUSTER_NAME" ssl-ssl --template "{{ .data \"tls.key\" }}")" ]'
  wait_until eval '[ "$(kubectl get secret -n "$CLUSTER_NAME" ssl-provided --template "{{ .data \"tls.key\" | base64decode }}")" = \
    "$(kubectl exec -n "$CLUSTER_NAME" "$CLUSTER_NAME-0" -c patroni -- cat /etc/ssl/tls.key)" ]'

  ssl_check
}

ssl_check() {
  local RETRY=3
  local EXIT_CODE RESULT
  while [ "$RETRY" -gt 0 ]
  do
    try_function wait_until run_query -m require -h "$CLUSTER_NAME" -i 1 -p 5432
    if "$RESULT"
    then
      break
    fi
    RETRY="$((RETRY - 1))"
  done

  RESPONSE_PRIMARY="$(wait_until run_query -m require -h "$CLUSTER_NAME" -i 1 -p 5432)"

  if [ "$RESPONSE_PRIMARY" = "1" ]
  then
    local RETRY=3
    local EXIT_CODE RESULT
    while [ "$RETRY" -gt 0 ]
    do
      if ! kubectl get sgcluster -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME" -o json | jq .spec.pods.disableEnvoy | grep -qxF true
      then
        if ! wait_until -t "$((E2E_TIMEOUT / 4))" run_query -m require -h "$CLUSTER_NAME"-replicas -i 0 -p 5432
        then
          echo "WARNING: SSL was not updated automatically... seems an envoy bug, will restart it"
          kubectl delete pod -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-1"
          wait_pods_running "$CLUSTER_NAMESPACE" 2
          wait_cluster "$CLUSTER_NAME" "$CLUSTER_NAMESPACE"
          switch_cluster_to_first "$CLUSTER_NAME" "$CLUSTER_NAMESPACE"
        fi
      fi
      try_function wait_until -t "$((E2E_TIMEOUT / 4))" run_query -m require -h "$CLUSTER_NAME"-replicas -i 0 -p 5432
      if "$RESULT"
      then
        break
      fi
      RETRY="$((RETRY - 1))"
    done

    RESPONSE_REPLICA="$(wait_until run_query -m require -h "$CLUSTER_NAME"-replicas -i 0 -p 5432)"
    if [ "$RESPONSE_REPLICA" = "1" ]
    then
      success "Connections are possible using SSL"
    else
      fail "Cannot connect to replica db using SSL"
    fi
  else
    fail "Cannot connect to primary db using SSL"
  fi
}

no_ssl_check() {
  RESPONSE_PRIMARY="$(run_query -m disable -h "$CLUSTER_NAME" -i 1 -p 5432)"

  if [ "$RESPONSE_PRIMARY" = "1" ]
  then
    RESPONSE_REPLICA="$(wait_until run_query -m disable -h "$CLUSTER_NAME"-replicas -i 0 -p 5432)"
    if [ "$RESPONSE_REPLICA" = "1" ]
    then
      success "Connections are possible without SSL"
    else
      fail "Cannot connect to replica db without SSL"
    fi
  else
    fail "Cannot connect to primary db without SSL"
  fi
}

replication_ssl_check() {
  kubectl delete pod -n "$CLUSTER_NAMESPACE" "$CLUSTER_NAME-1"
  if wait_until eval '[ "$(run_query -m disable -h "$CLUSTER_NAME" -i 1 -p 5432 \
    -q "SELECT ssl FROM pg_stat_ssl INNER JOIN pg_stat_activity ON pg_stat_ssl.pid = pg_stat_activity.pid WHERE usename = '"'"'replicator'"'"'")" = "t" ]'
  then
    success "Replication is using SSL"
  else
    fail "Replication is not using SSL"
  fi
}
